//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using OpenLS.Spreadsheet.UI.Internals;
using OpenLS.UI;

namespace OpenLS.Spreadsheet.UI
{
    static class GridZooming
    {
        public static void EnableCommands(UIElement g)
        {
            g.CommandBindings.Add(new CommandBinding(ViewCommands.SetZoom100,
                OnSetZoom100, Always));
            g.CommandBindings.Add(new CommandBinding(ViewCommands.SetZoom,
                OnSetZoom, Always));
            g.CommandBindings.Add(new CommandBinding(ViewCommands.ZoomToSelection, OnZoomToSelection, Always));
        }

        private static void Always(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = true;
            args.Handled = true;
        }
        static Worksheet GetWorksheet(object sender)
        {
            return WorksheetHelper.GetWorksheet(sender);
        }

        static void OnSetZoom100(object sender, ExecutedRoutedEventArgs args)
        {
            Worksheet CurrentWorksheet = GetWorksheet(sender);
            if (CurrentWorksheet == null)
                return;
            CurrentWorksheet.View.ZoomScale = 100;
        }
        static void OnZoomToSelection(object sender, ExecutedRoutedEventArgs args)
        {
            args.Handled = true;
            Worksheet worksheet = GetWorksheet(sender);
            var element = (FrameworkElement) sender;
            element = Enumerable.First(Enumerable.OfType<WorksheetPanel>(WindowServices.GetAncestors(element)));
            Contract.Assert(element != null);
            ZoomToSelection(worksheet, element);
        }

        private static void ZoomToSelection(Worksheet worksheet, FrameworkElement element)
        {
            Range selection = worksheet.Selection;
            double selectionWidth = 0;
            double selectionHeight = 0;
            var columns = selection.GetColumns();
            var rows = selection.GetRows();
            if (worksheet.Pane != null)
            {
                var pane2 = worksheet.Pane;
                if (pane2.ColumnCount != null &&
                    pane2.ColumnCount.Value < selection.Address.TopRight.Column)
                {
                    RangeAddress address = selection.Address;
                    selection = CellsRange.Create(worksheet,
                                                  new RangeAddress(new CellAddress(address.TopLeft.Row, 0),
                                                                   address.BottomRight));
                    IWorksheetFragment f = worksheet.TopLeftPane;
                    var r = CellsRange.Create(worksheet,
                                                  new RangeAddress(new CellAddress(address.TopLeft.Row, worksheet.TopRightPane.Left),
                                                                   address.BottomRight));
                    Debug.WriteLine(worksheet.TopLeftPane.Right);
                    Debug.WriteLine(worksheet.TopRightPane.Left);
                    Contract.Assert(worksheet.TopLeftPane.Right <= worksheet.TopRightPane.Left);
                    columns = Enumerable.Union(f.GetColumns(), r.GetColumns());
                  //  Debug.WriteLine(string.Join("||", Enumerable.Select(columns, c => c.Label)));
                    Debug.Assert(Enumerable.Count(columns) == Enumerable.Count(Enumerable.Distinct(columns)));

                }
                if (pane2.RowCount != null &&
                    pane2.RowCount.Value < selection.Address.TopRight.Row)
                {
                    RangeAddress address = selection.Address;
                    selection = CellsRange.Create(worksheet,
                                                  new RangeAddress(new CellAddress(0, address.TopLeft.Column),
                                                                   address.BottomRight));
                    IWorksheetFragment f = worksheet.TopLeftPane;
                    var r = CellsRange.Create(worksheet,
                                                  new RangeAddress(new CellAddress(worksheet.BottomLeftPane.Top, address.TopLeft.Column),
                                                                   address.BottomRight));
                    rows = Enumerable.Union(f.GetRows(), r.GetRows());
                    Debug.Assert(Enumerable.Count(rows) == Enumerable.Count(Enumerable.Distinct(rows)));
                }
            }
            if (selection is CellsRange)
            {
                selectionWidth = Enumerable.Sum(Enumerable.Select(columns, c => c.ActualWidth));
                selectionHeight = Enumerable.Sum(Enumerable.Select(rows, c => c.ActualHeight));
            }
            if (selection is FullColumnRange)
            {
                selectionWidth = Enumerable.Sum(Enumerable.Select(columns, c => c.ActualWidth));

            }
            if (selection is FullRowRange)
            {
                selectionHeight = Enumerable.Sum(Enumerable.Select(rows, c => c.ActualHeight));
            }
            if (selectionHeight == 0 && selectionWidth == 0)
                return;
            double zoom = 400;
            double scaling = worksheet.View.ZoomScale/100d;
            if (selectionWidth > 0)
                zoom = element.ActualWidth * scaling / selectionWidth * 100;
            if (selectionHeight > 0)
                zoom = Math.Min(zoom, element.ActualHeight * scaling / selectionHeight * 100);
            zoom = Math.Max(zoom, 10);
            worksheet.View.ZoomScale = (int)zoom;
            var pane = worksheet.GetPaneFor(selection.TopLeftCell);
            //  pane.EnsureVisible(selection.TopLeftCell);
            pane.EnsureVisible(selection);
//            pane.Top = selection.TopLeftCell.Row.Index;
  //          pane.Left = selection.TopLeftCell.Column.Index;
        }

        static void OnSetZoom(object sender, ExecutedRoutedEventArgs args)
        {
            Worksheet CurrentWorksheet = GetWorksheet(sender);
            if (CurrentWorksheet == null)
                return;
            var w = new ZoomControl {Zoom = (CurrentWorksheet.View.ZoomScale)};
            WindowServices.ShowDialog(
                w, OpenLS.UI.Internals.UIStringTable.Zoom, sender as UIElement,
                delegate
                    {
                        if (w.FitToSelection)
                        {
                            var element = (FrameworkElement) sender;
                            element = WindowServices.GetAncestor<WorksheetPanel>(element);
                            ZoomToSelection(CurrentWorksheet, element);
                        }
                        else   
                        CurrentWorksheet.View.ZoomScale = w.Zoom;
                    }, o=>false);
            args.Handled = true;
        }


    }
}
